package net.sf.rose.business.service;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import net.sf.rose.business.bean.base.FileBean;
import net.sf.rose.business.bean.database.DataTypeMetaBean;
import net.sf.rose.business.bean.database.DataTypeMetaBeans;
import net.sf.rose.business.service.function.Jdbc;
import net.sf.rose.business.service.function.Mysql;
import net.sf.rose.exception.SystemErrorCode;
import net.sf.rose.exception.SystemException;
import net.sf.rose.jdbc.KeyGenerator;
import net.sf.rose.jdbc.GenericDAO;
import net.sf.rose.jdbc.QueryBeanSQL;
import net.sf.rose.jdbc.UserBean;
import net.sf.rose.jdbc.service.DataBaseFactory;
import net.sf.rose.jdbc.service.Service;
import net.sf.rose.util.DateUtil;

import org.apache.log4j.Logger;
import org.simpleframework.xml.ElementMap;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;

/**
 * @author fengjian
 * @since 2014/05/25
 */
public class DBMetaService {

	private static Logger logger = Logger.getLogger(DBMetaService.class);

	/** 存储在数据库中的名称 */
	private static String NAME = "db_meta";

	/** 存储在数据库中的分类名称 */
	private static String SORT = "config";

	/** 本类的单例 */
	private static DBMetaService service = null;

	/** 数据类的单例 */
	private static FileBean fileBean = null;

	static {
		Service s = DataBaseFactory.getService();
		UserBean user = new UserBean();
		user.setUserName("system");
		s.setUser(user);
		GenericDAO dao = new GenericDAO(s);
		QueryBeanSQL query = new QueryBeanSQL(s);
		fileBean = new FileBean();
		fileBean.setCode(NAME);
		fileBean.setFileSort(SORT);
		try {
			query.createListSql(fileBean);
			Object obj = dao.load(query);
			if (obj != null) {
				fileBean = (FileBean) obj;
				InputStream in = fileBean.getFile();
				if (in != null) {
					Serializer serializer = new Persister();
					service = serializer.read(DBMetaService.class, in);
					logger.info("成功地从数据库中读取了数据库元数据！");
				}
			}
			if (service == null) {
				service = new DBMetaService();
				logger.info("数据库元数据初始化...");
			}
		} catch (SystemException e) {
			logger.error("数据库元数据从数据库读取时操作失败！", e);
			throw e;
		} catch (Exception e) {
			String message = "数据库元数据初始化失败！";
			logger.error(message, e);
			throw new SystemException(message, SystemErrorCode.APPLICATION_ERROR);
		} finally {
			s.close();
		}
	}

	/**
	 * 
	 */
	public static void save(UserBean user) {
		Service s = DataBaseFactory.getService();
		GenericDAO dao = new GenericDAO(s);
		QueryBeanSQL query = new QueryBeanSQL(s);
		try {
			Serializer serializer = new Persister();
			File file = new File(System.getenv("TEMP"), KeyGenerator.getUID());
			serializer.write(service, file);
			InputStream in = new FileInputStream(file);
			fileBean.setFile(in);
			if (fileBean.getFileID() == null) {
				fileBean.setFileID(KeyGenerator.getUID());
				fileBean.setCreateUser(user.getUserName());
				fileBean.setCreateTime(DateUtil.getTimestamp());
				query.createInsertSql(fileBean);
			} else {
				fileBean.setUpdateUser(user.getUserName());
				fileBean.setUpdateTime(DateUtil.getTimestamp());
				query.createUpdateSql(fileBean);
			}
			dao.update(query);
			s.commit();
		} catch (SystemException e) {
			logger.error("数据库元数据保存至数据库操作失败！", e);
			throw e;
		} catch (Exception e) {
			String message = "数据库元数据保存失败！";
			logger.error(message, e);
			throw new SystemException(message, SystemErrorCode.APPLICATION_ERROR);
		} finally {
			s.close();
		}
	}

	/**
	 * 
	 */
	public static void input(InputStream in) {
		try {
			if (in != null) {
				Serializer serializer = new Persister();
				service = serializer.read(DBMetaService.class, in);
				logger.info("成功地从导入文件中读取了数据字典！");
			}
		} catch (Exception e) {
			String message = "数据字典导入失败！";
			logger.error(message, e);
			throw new SystemException(message, SystemErrorCode.APPLICATION_ERROR);
		}
	}

	/**
	 * 
	 */
	public static File output() {
		try {
			Serializer serializer = new Persister();
			File file = new File(System.getenv("TEMP"), KeyGenerator.getUID());
			serializer.write(service, file);
			return file;
		} catch (Exception e) {
			String message = "数据字典导出失败！";
			logger.error(message, e);
			throw new SystemException(message, SystemErrorCode.APPLICATION_ERROR);
		}
	}

	public static DBMetaService getService() {
		return service;
	}

	public static Map<String, DataTypeMetaBeans> getAll() {
		return service.database;
	}

	/** 所有定义的 */
	@ElementMap(required = false)
	private Map<String, DataTypeMetaBeans> database = new LinkedHashMap<String, DataTypeMetaBeans>();

	/**
	 * 返回系统已定义的数据库字段类型
	 */
	public List<String> getAllDataType() {
		List<String> list = new ArrayList<String>();
		DataTypeMetaBeans m = getUsedDataTypeMetaBeans();
		if (m != null) {
			for (DataTypeMetaBean t : m.getDataMetas()) {
				list.add(t.getName());
			}
		}
		return list;
	}

	/**
	 * 返回系统当前使用的数据库类型
	 */
	public DataTypeMetaBeans getUsedDataTypeMetaBeans() {
		for(DataTypeMetaBeans m : database.values()){
			if(m.isUsed()){
				return m;
			}
		}
		return null;
	}

	/**
	 * 返回系统当前使用的数据库的操作接口类
	 */
	protected Jdbc getJdbcBean() {
		DataTypeMetaBeans m = getUsedDataTypeMetaBeans();
		Jdbc jdbc = null;
		if (m != null) {
			String name = m.getName();
			if (name.equals("mysql")) {
				jdbc = new Mysql();
			}
			Map<String, DataTypeMetaBean> map = new HashMap<String, DataTypeMetaBean>();
			for(DataTypeMetaBean d : m.getDataMetas()){
				map.put(d.getName(), d);
			}
			jdbc.setDataTypeMetaBeans(map);
		}
		return jdbc;
	}
}
